package com.eic.framework.core.util;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.common.utils.SecurityUtils;
import com.eic.framework.core.annotation.*;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 新增、删除、修改时设置时间、用户信息
 */
public class CreateAndUpdateMetaUtils {
    private static Map<Class,TableFieldMeta> metaMap=new HashMap<>();

    /**
     * 新增数据时，设置操作人、操作时间、修改人、修改时间
     */
    public static void insertFill(Object entity) {
        try{
            TableFieldMeta meta=getMeta(entity.getClass());
            setOperTime(entity,meta.getInsertTimeField());
            setOperTime(entity,meta.getUpdateTimeField());
            setOperUser(entity,meta.getInsertUserField());
            setOperUser(entity,meta.getUpdateUserField());
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }
    /**
     * 修改数据时，设置修改人、修改时间
     */
    public static void updateFill(Object entity) {
        try{
            TableFieldMeta meta=getMeta(entity.getClass());
            setValue(entity,meta.getInsertTimeField(),null);
            setValue(entity,meta.getInsertUserField(),null);
            setOperTime(entity,meta.getUpdateTimeField());
            setOperUser(entity,meta.getUpdateUserField());
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }

    /**
     * 有逻辑删除字段，放回修改条件
     */
    public static UpdateWrapper logicDel(Class cls, Collection<? extends Serializable> idList){
        try{
            TableFieldMeta meta=getMeta(cls);
            if(meta.getDeleteLogicField()!=null){
                UpdateWrapper wrapper= Wrappers.update().set(meta.getLogicDelFieldName(),"1");
                if(meta.getUpdateTimeFieldName()!=null){
                    wrapper.set(meta.getUpdateTimeFieldName(),new Date());
                }
                if(meta.getUpdateUserField()!=null){
                    wrapper.set(meta.getUpdateUserFieldName(), SecurityUtils.getLoginUser().getUserId());
                }
                wrapper.in(meta.getPrimaryFieldName(),idList);
                return wrapper;
            }else{
                return null;
            }
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }

    /**
     * 字段设置值：操作人
     */
    private static void setOperUser(Object entity,Field field) throws IllegalAccessException {
        if(field!=null){
            if(field.getType() == String.class){
                field.set(entity,SecurityUtils.getLoginUser().getUserId().toString());
            }else{
                field.set(entity,SecurityUtils.getLoginUser().getUserId());
            }
        }
    }
    /**
     * 字段设置值：操作时间
     */
    private static void setOperTime(Object entity,Field field) throws IllegalAccessException {
        if(field!=null){
            if(field.getType() == Date.class){
                field.set(entity,new Date());
            }
        }
    }

    private static void setValue(Object entity,Field field,Object value) throws IllegalAccessException {
        if(field!=null){
            field.set(entity,value);
        }
    }

    /**
     * 初始化字段注解信息
     */
    public static TableFieldMeta getMeta(Class cls){
        TableFieldMeta meta=metaMap.get(cls);
        if(meta!=null){
            return meta;
        }
        meta=new TableFieldMeta();
        metaMap.put(cls,meta);
        while (Object.class != cls) {
            for(Field field:cls.getDeclaredFields()){
                if(meta.getPrimaryFieldName()==null && field.getAnnotation(TableId.class)!=null){
                    field.setAccessible(true);
                    meta.setPrimaryField(field);
                    TableId idAnno=field.getAnnotation(TableId.class);
                    meta.setPrimaryFieldName(idAnno.value());
                }
                if(meta.getInsertTimeField()==null && field.getAnnotation(InsertTime.class)!=null){
                    field.setAccessible(true);
                    meta.setInsertTimeField(field);
                }
                if(meta.getInsertUserField()==null && field.getAnnotation(InsertUser.class)!=null){
                    field.setAccessible(true);
                    meta.setInsertUserField(field);
                }
                if(meta.getUpdateTimeField()==null && field.getAnnotation(UpdateTime.class)!=null){
                    meta.setUpdateTimeFieldName(getFieldName(field));
                    field.setAccessible(true);
                    meta.setUpdateTimeField(field);
                }
                if(meta.getUpdateUserField()==null && field.getAnnotation(UpdateUser.class)!=null){
                    meta.setUpdateUserFieldName(getFieldName(field));
                    field.setAccessible(true);
                    meta.setUpdateUserField(field);
                }
                if(meta.getDeleteLogicField()==null && field.getAnnotation(TableLogic.class)!=null){
                    meta.setLogicDelFieldName(getFieldName(field));
                    field.setAccessible(true);
                    meta.setDeleteLogicField(field);
                }
            }
            cls = cls.getSuperclass();
        }
        return meta;
    }

    /**
     * 获取数据库表字段名称
     */
    private static String getFieldName(Field field){
        if(field.getAnnotation(TableField.class)!=null){
            TableField anno=field.getAnnotation(TableField.class);
            return anno.value();
        }else{
            return StringUtils.camelToUnderline(field.getName());
        }
    }
}
